/*
 * Firmware for GSC count and energy monitor on Arduino in combination with XPORT
 *
 * This firmware is arduino version dependent:
 *  -> Arduino duemilanova
 *          ~ only has 1 uart, so NewSoftSerial library is used
 *          ~ only 2 interupt pins, so monitoring of water!
 *  -> Arduino mega
 *          ~ has multiple hardware uarts, so no need for use of NewSoftSerial library
 *          ~ has up to 4 interrupt pins, so monitoring of water is also possible
 *
 * My connections between Arduino-XPORT (via defines):
 *	# TX - pin4/pin18 - red
 * 	# RX - pin5/pin19 - blue
 *      # RESET - pin 6 - yellow
 *	# GND - white
 *
 * Note: It is also possible to allow incoming telnet connections
 *       just use the IP number and the fixed telnet port 10001
 *          e.g.: telnet 192.168.123.102 10001
 *
 * What is being monitored:
 *  -> GSC count
 *  -> gas meter
 *  -> water meter (Arduino mega only!)
 *
 */

#define TEMP_MEASUREMENT
#ifdef TEMP_MEASUREMENT
#include <OneWire.h>
#endif

#define ARDUINO_MEGA
#define USB_SERIAL_SPEED 57600

#include "TimerOne.h"
#ifndef ARDUINO_MEGA
#include <NewSoftSerial.h>
#endif

#define GSC_INTERRUPT_MODE  RISING  /* for GND ref, pulled to VDC when triggered */
#define GSC_INTERRUPT_PIN   0       /* 0 = digital pin2, 1 = digital pin 3 */
#define GSC_INTERRUPT_PINNB 2       /* pin nb */

#define GAS_INTERRUPT_PIN   1
#define GAS_INTERRUPT_PINNB 3
#define GAS_INTERRUPT_MODE  FALLING /* for GND ref, pulled to VDC when triggered */

#define WAT_INTERRUPT_PIN   2
#define WAT_INTERRUPT_PINNB 21
#define WAT_INTERRUPT_MODE  FALLING /* for GND ref, pulled to VDC when triggered */

#define LED_PIN             13      /* default LED pin */
#define TIMER_IN_SECONDS    15*60*20   /* 15 minute intervals */
#define ERROR_COUNT_HTTP_OUTGOING 45*20 /* 45 sec timout for http outgoing */
#define ERROR_COUNT_HTTP_INCOMING 45*20 /* 45 sec timout for http incoming */

#ifdef ARDUINO_MEGA
// non-mega: use soft serial
#define XPORT_SERIAL_TX_PIN 4 /* red  */
#define XPORT_SERIAL_RX_PIN 5 /* blue */
#else
// mega use (Serial 1: 19 (RX) and 18 (TX))
#define XPORT_SERIAL_TX_PIN 18 /* red  */
#define XPORT_SERIAL_RX_PIN 19 /* blue */
#endif
#define XPORT_RESET_PIN 6
#define XPORT_SERIAL_SPEED 57600

#define ENABLE_ETHERNET_MODE

#define PULSE_COUNT_GSC_CONFIRM  2  /* number of 50ms frames before confirming gsc pulse */
#define PULSE_COUNT_GAS_CONFIRM  2  /* number of 50ms frames before confirming gas pulse */
#define PULSE_COUNT_WAT_CONFIRM  2  /* number of 50ms frames before confirming gas pulse */

static unsigned long GscPulseCount                = 0;
static unsigned long GscPulseCount_prev           = 0;
static unsigned long GscPulseCount_diff           = 0;
static unsigned long GscPulseCount_did_not_work   = 0;

static unsigned long GasPulseCount                = 0;
static unsigned long GasPulseCount_prev           = 0;
static unsigned long GasPulseCount_diff           = 0;
static unsigned long GasPulseCount_did_not_work   = 0;

static unsigned long WatPulseCount                = 0;
static unsigned long WatPulseCount_prev           = 0;
static unsigned long WatPulseCount_diff           = 0;
static unsigned long WatPulseCount_did_not_work   = 0;

static unsigned long SecondCount_GSC = 0;
static unsigned long SecondCount_GAS = TIMER_IN_SECONDS/3;     // Start at different time, so no overlap
static unsigned long SecondCount_WAT = (TIMER_IN_SECONDS/3)*2; // Start at different time, so no overlap

static long OutgoingCount = 0;
static long IncomingCount = 0;

static bool led_state               = false;
static unsigned char  led_count     = 0;
static bool add_to_count_gsc        = false;
static bool add_to_count_gas        = false;
static bool add_to_count_wat        = false;
static bool confirm_pulse_gsc       = false;
static int  confirm_pulse_gsc_count = 0;
static bool confirm_pulse_gas       = false;
static int  confirm_pulse_gas_count = 0;
static bool confirm_pulse_wat       = false;
static int  confirm_pulse_wat_count = 0;

#ifdef ENABLE_ETHERNET_MODE
#ifndef ARDUINO_MEGA
  NewSoftSerial Serial1(XPORT_SERIAL_RX_PIN,XPORT_SERIAL_TX_PIN);
#endif
  enum HttpStatusEnum { HTTP_IDLE, HTTP_CONNECT, HTTP_WAIT_FOR_ACK, HTTP_TRANSFER, HTTP_DISCONNECTED };
  enum HttpStatusEnum HttpStatus;
  int input = 0;
#define RETURNSTR_LENGTH 64
  char ReturnStr[RETURNSTR_LENGTH];
  int  ReturnStrCounter;
  bool string_start;
  enum HttpMessageEnum { HTTP_GET_TIME, HTTP_POST_GSC_VALUE, HTTP_POST_GAS_VALUE, HTTP_POST_WAT_VALUE, 
                         HTTP_POST_GSC_VALUE_NO_SUCCEED, HTTP_POST_GAS_VALUE_NO_SUCCEED, HTTP_POST_WAT_VALUE_NO_SUCCEED, 
                         HTTP_TEST_POST };
  enum HttpMessageEnum HttpMessage;
  enum XportStatusEnum { XPORT_IDLE, XPORT_RESET, XPORT_OUTGOING, XPORT_WAIT_FOR_INCOMING, XPORT_INCOMING };
  enum XportStatusEnum XportStatus;

void xportReset()
{
  pinMode(XPORT_RESET_PIN, OUTPUT);
  digitalWrite(XPORT_RESET_PIN, LOW);
  delay(100);
  digitalWrite(XPORT_RESET_PIN, HIGH);
  delay(3000);
  XportStatus = XPORT_IDLE;
}

void xportClear()
{
  Serial1.flush();
  // Read every remaining data from Xport
  while(Serial1.available()){
    input = Serial1.read();
  }
}

/* HTTP transfer, driven by HttpMessage enumerated type */
int HttpTransfer(int value = 0)                     
{
  OutgoingCount = ERROR_COUNT_HTTP_OUTGOING;
  XportStatus = XPORT_OUTGOING;
  bool PrintReturnString = false;
  do{
	switch(HttpStatus){
	case HTTP_IDLE:
		HttpStatus = HTTP_CONNECT;
	case HTTP_CONNECT:
		//Serial.print("\n\t ### Send the command for connection (C67.220.217.229/80) -> going to HTTP_WAIT_FOR_ACK");
		//Serial1.print("C67.220.217.230/80\n");
                Serial1.print("Cshredcat.heliohost.org/80\n");
		HttpStatus = HTTP_WAIT_FOR_ACK;
		break;
	case HTTP_WAIT_FOR_ACK:
		if(Serial1.available()){
			if( (char)Serial1.read() == 'C'){
                          switch(HttpMessage){
                          case HTTP_GET_TIME:
				//Serial.print("\n\t ### Send the GET request (GET /time_fw.php HTTP/1.1\nHost: shredcat.heliohost.org\n\n) -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/time_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                PrintReturnString = true;
                                break;
                          case HTTP_POST_GSC_VALUE:
				//Serial.print("\n\t ### Send the GET request -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/add_gsc_value_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                break;
                          case HTTP_POST_GAS_VALUE:
				//Serial.print("\n\t ### Send the GET request -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/add_gas_value_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                break;
                          case HTTP_POST_WAT_VALUE:
				//Serial.print("\n\t ### Send the GET request -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/add_wat_value_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                break;
                          case HTTP_POST_GSC_VALUE_NO_SUCCEED:
				//Serial.print("\n\t ### Send the GET request -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/add_gsc_value_no_succeed_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                break;
                          case HTTP_POST_GAS_VALUE_NO_SUCCEED:
				//Serial.print("\n\t ### Send the GET request -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/add_gas_value_no_succeed_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                break;
                          case HTTP_POST_WAT_VALUE_NO_SUCCEED:
				//Serial.print("\n\t ### Send the GET request -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/add_wat_value_no_succeed_fw.php?val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                break;
                          case HTTP_TEST_POST:
				//Serial.print("\n\t ### Send the GET request (GET /time_fw.php HTTP/1.1\nHost: shredcat.heliohost.org\n\n) -> going to HTTP_TRANSFER");
		    		Serial1.print("GET /my_php/post_result_fw.php?nr=");
				Serial1.print(value);
		    		Serial1.print("&val=");
				Serial1.print(value);
				Serial1.print(" HTTP/1.1\nHost: shredcat.heliohost.org\n\n");
                                PrintReturnString = true;
                                break;
                          }   
  			  HttpStatus = HTTP_TRANSFER;
			}else{
				HttpStatus = HTTP_IDLE;
			}
		}
		break;
	case HTTP_TRANSFER:
		if(Serial1.available()){
			input = (char)Serial1.read();
                        switch(input){
                        case '[':
				// Found start of string
				string_start = true;
                                break;
                        case ']':
				HttpStatus = HTTP_DISCONNECTED;
				string_start = false;
				break;
			default:
				if(string_start){
					ReturnStr[ReturnStrCounter++] = input;
					if(ReturnStrCounter == RETURNSTR_LENGTH){
						HttpStatus = HTTP_DISCONNECTED;
						string_start = false;
					}
				}
                                break;
			}
		}
		break;
	case HTTP_DISCONNECTED:
                Serial1.flush(); 
		// Print the string:
                if(PrintReturnString){
  		  Serial.print("\n --> Answer from server: ");
		  for(int i=0;i<ReturnStrCounter;i++){
			Serial.print((char)ReturnStr[i]);
		  }
                }

		// Read every remaining data from Xport
		while(Serial1.available()){
			input = Serial1.read();
		}
                Serial1.print('D');
                Serial1.flush();                
		XportStatus = XPORT_IDLE;
		break;
	}
  }while(XportStatus == XPORT_OUTGOING);
  
  // Reset Xport when timeout
  bool error_tmp = false;
  if(XportStatus == XPORT_RESET){
    error_tmp = true;
  }

  // Reset loop vars
  HttpStatus = HTTP_IDLE;
  ReturnStrCounter = 0;
  string_start = false;
  
  if(error_tmp)
    return 0;
  return 1;
}
#endif


#ifdef TEMP_MEASUREMENT
#define TEMP_ERROR_VALUE -1000
// Enable following define for extra debug info
//#define TEMPSENSOR_DBG_PRINTS

// DS18S20 Temperature chip i/o
//  Usage:
//     OneWire ds(10);  // on pin 10
//     double temp = GetTempValue(&ds);
/*
Device address:
  DS18B20: 0x28
  DS18S20: 0x10
*/
double convert_hex_to_temp_B_series(byte data[12]){
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

 LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;

  /*
  if (SignBit) // If its negative
  {
     Serial.print("-");
  }
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 10)
  {
     Serial.print("0");
  }
  Serial.print(Fract);

  Serial.print("\n");
  */

  double temp = Whole + (Fract/100);
  if(SignBit){temp = -temp;}
  return temp;
}

double convert_hex_to_temp_S_series(byte data[12]){
int HighByte, LowByte, TReading, SignBit, Tc_10, Whole, Fract;


 LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_10 = (5 * TReading);    // multiply by 5

  Whole = Tc_10 / 10;  // separate off the whole and fractional portions
  Fract = Tc_10 % 10;

  /*
  if (SignBit) // If its negative
  {
     Serial.print("-");
  }
  Serial.print(Whole);
  Serial.print(".");
  if (Fract < 10)
  {
     Serial.print("0");
  }
  Serial.print(Fract);

  Serial.print("\n");
  */

  double temp = Whole + (Fract/100);
  if(SignBit){temp = -temp;}
  return temp;
}


double GetTempValue(OneWire *ds) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  if ( !ds->search(addr)) {
#ifdef TEMPSENSOR_DBG_PRINTS    
      Serial.print("No more addresses.\n");
#endif
      ds->reset_search();
      return TEMP_ERROR_VALUE;
  }
  
#ifdef TEMPSENSOR_DBG_PRINTS   
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(addr[i], HEX);
    Serial.print(" ");
  }
#endif

  if ( OneWire::crc8( addr, 7) != addr[7]) {
#ifdef TEMPSENSOR_DBG_PRINTS      
      Serial.print("CRC is not valid!\n");
#endif
      return TEMP_ERROR_VALUE;
  }

  if ( addr[0] != 0x28) {
#ifdef TEMPSENSOR_DBG_PRINTS      
      Serial.print("Device is not a DS18S20 family device.\n");
#endif
      delay(1000);
      return TEMP_ERROR_VALUE;
  }
  
  ds->reset();
  ds->select(addr);
  ds->write(0x44,1);         // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds->depower() here, but the reset will take care of it.

  present = ds->reset();
  ds->select(addr);    
  ds->write(0xBE);         // Read Scratchpad

#ifdef TEMPSENSOR_DBG_PRINTS  
  Serial.print("P=");
  Serial.print(present,HEX);
  Serial.print(" ");
#endif
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds->read();
#ifdef TEMPSENSOR_DBG_PRINTS  
    Serial.print(data[i], HEX);
    Serial.print(" ");
#endif
  }
#ifdef TEMPSENSOR_DBG_PRINTS  
  Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  Serial.println();
#endif
  
  double tmp = convert_hex_to_temp_B_series(data);
  return tmp;
}
#endif


void setup()
{
  pinMode(LED_PIN, OUTPUT);
  pinMode(GSC_INTERRUPT_PINNB, INPUT);
  attachInterrupt(GSC_INTERRUPT_PIN, gsc_count_debounce, GSC_INTERRUPT_MODE);
  pinMode(GAS_INTERRUPT_PINNB, INPUT);
  attachInterrupt(GAS_INTERRUPT_PIN, gas_count_debounce, GAS_INTERRUPT_MODE);
  pinMode(WAT_INTERRUPT_PINNB, INPUT);
  attachInterrupt(WAT_INTERRUPT_PIN, wat_count_debounce, WAT_INTERRUPT_MODE);
  
  Serial.begin(USB_SERIAL_SPEED); 

  digitalWrite(LED_PIN, true); // disable the LED

  Timer1.initialize();     // initialize timer1 and set period every second
  Timer1.attachInterrupt(timer_expires,50000);  // attaches function as a timer overflow interrupt

#ifdef ENABLE_ETHERNET_MODE
  Serial1.begin(XPORT_SERIAL_SPEED);
  xportClear();
  xportReset();
  xportClear();
#endif

  print_menu();
}


void loop()
{
  /* DRIVING THE LED */
  led_state = (led_count & 0x10) >>4;
  digitalWrite(LED_PIN, led_state); // drive the LED
  
  // Process commands when available:
  if(Serial.available()){
    process_char(Serial.read());
  }
  
  /* ADD VALUE TO GSC COUNT */
  if(add_to_count_gsc & (XportStatus == XPORT_IDLE)){
#ifdef ENABLE_ETHERNET_MODE
    HttpMessage = HTTP_POST_GSC_VALUE;
    if(HttpTransfer(GscPulseCount_diff)){
	//GscPulseCount_did_not_work = 0;
    }else{
	GscPulseCount_did_not_work += GscPulseCount_diff;
    }
    if(GscPulseCount_did_not_work){
    	HttpMessage = HTTP_POST_GSC_VALUE_NO_SUCCEED;
        if(HttpTransfer(GscPulseCount_did_not_work)){
	    GscPulseCount_did_not_work = 0;
        }
    }
#endif
    add_to_count_gsc = false;
  }

  /* ADD VALUE TO GAS COUNT */
  if(add_to_count_gas & (XportStatus == XPORT_IDLE)){
#ifdef ENABLE_ETHERNET_MODE
    HttpMessage = HTTP_POST_GAS_VALUE;
    if(HttpTransfer(GasPulseCount_diff)){
	//GasPulseCount_did_not_work = 0;
    }else{
	GasPulseCount_did_not_work += GasPulseCount_diff;
    }
    if(GasPulseCount_did_not_work){
        HttpMessage = HTTP_POST_GAS_VALUE_NO_SUCCEED;
        if(HttpTransfer(GasPulseCount_did_not_work)){
	    GasPulseCount_did_not_work = 0;
        }
    }
#endif
    add_to_count_gas = false;
  }

  /* ADD VALUE TO WAT COUNT */
  if(add_to_count_wat & (XportStatus == XPORT_IDLE)){
#ifdef ENABLE_ETHERNET_MODE
    HttpMessage = HTTP_POST_WAT_VALUE;
    if(HttpTransfer(WatPulseCount_diff)){
	//WatPulseCount_did_not_work = 0;
    }else{
	WatPulseCount_did_not_work += WatPulseCount_diff;
    }
    if(WatPulseCount_did_not_work){
        HttpMessage = HTTP_POST_WAT_VALUE_NO_SUCCEED;
        if(HttpTransfer(WatPulseCount_did_not_work)){
	    WatPulseCount_did_not_work = 0;
        }
    }
#endif
    add_to_count_wat = false;
  }

  if(Serial1.available() && (XportStatus == XPORT_IDLE)){
    if( (char)Serial1.read() == 'C'){
      IncomingCount = ERROR_COUNT_HTTP_INCOMING;
      XportStatus = XPORT_WAIT_FOR_INCOMING;
    }
  }

  if(Serial1.available() && (XportStatus == XPORT_WAIT_FOR_INCOMING)){
    if( (char)Serial1.read() == 'I'){
      XportStatus = XPORT_INCOMING;
    }
  }
  
  if(Serial1.available() && (XportStatus == XPORT_INCOMING)){
    // Process the command which was incoming
    input = (char)Serial1.read();
    switch(input){
    case 'X':
	// info
        Serial1.print("Xport debug info\r\n=================\r\n");
        Serial1.print(" * GSC second count :"); Serial1.print(SecondCount_GSC); Serial1.print("\r\n");
        Serial1.print(" * GSC pulse count  :"); Serial1.print(GscPulseCount);  Serial1.print("\r\n");
        Serial1.print(" * GAS second count :"); Serial1.print(SecondCount_GAS); Serial1.print("\r\n");
        Serial1.print(" * GAS pulse count  :"); Serial1.print(GasPulseCount);  Serial1.print("\r\n");
        Serial1.print(" * WAT second count :"); Serial1.print(SecondCount_WAT); Serial1.print("\r\n");
        Serial1.print(" * WAT pulse count  :"); Serial1.print(WatPulseCount);  Serial1.print("\r\n");
        XportStatus = XPORT_INCOMING;
        break;
    case 'D':
	// disconnect
        Serial1.print("Disconnnecting ...\r\n");
        XportStatus = XPORT_RESET;
        break;
    case '?':
        // TBD
        Serial1.print("Xport unknown command\r\n");
        Serial1.print("List of commands:\r\n");
        Serial1.print(" * 'X' : debug info\r\n");
        Serial1.print(" * '?' : this menu\r\n");
        XportStatus = XPORT_INCOMING;
        break;
     //default:
        //Serial1.print("Unknown command (press '?' for help)\r\n");
    }
  }
  
  if(XportStatus == XPORT_RESET){
    xportClear();
    xportReset();
    xportClear();
    XportStatus = XPORT_IDLE;  
  }

}

void timer_expires()
{
  if(confirm_pulse_gsc){
    if((--confirm_pulse_gsc_count) == 0){
      if(digitalRead(GSC_INTERRUPT_PINNB)){
        GscPulseCount++;
      }
      confirm_pulse_gsc = false;
    }
  }

  if(confirm_pulse_gas){
    if((--confirm_pulse_gas_count) == 0){
      if(digitalRead(GAS_INTERRUPT_PINNB) == 0){
        GasPulseCount++;
      }
      confirm_pulse_gas = false;
    }
  }

  if(confirm_pulse_wat){
    if((--confirm_pulse_wat_count) == 0){
      if(digitalRead(WAT_INTERRUPT_PINNB) == 0){
        WatPulseCount++;
      }
      confirm_pulse_wat = false;
    }
  }

  led_count++;
    
  if(++SecondCount_GSC >= TIMER_IN_SECONDS){
    SecondCount_GSC = 0; 
    GscPulseCount_diff = GscPulseCount - GscPulseCount_prev;
    GscPulseCount_prev = GscPulseCount;
    add_to_count_gsc = true;
  }
  if(++SecondCount_GAS >= TIMER_IN_SECONDS){
    SecondCount_GAS = 0; 
    GasPulseCount_diff = GasPulseCount - GasPulseCount_prev;
    GasPulseCount_prev = GasPulseCount;
    add_to_count_gas = true;
  }
  if(++SecondCount_WAT >= TIMER_IN_SECONDS){
    SecondCount_WAT = 0; 
    WatPulseCount_diff = WatPulseCount - WatPulseCount_prev;
    WatPulseCount_prev = WatPulseCount;
    add_to_count_wat = true;
  }
  
  if(XportStatus == XPORT_OUTGOING){
    if(--OutgoingCount == 0){
      XportStatus = XPORT_RESET;
    }
  }
  if((XportStatus == XPORT_INCOMING)||(XportStatus == XPORT_WAIT_FOR_INCOMING)){
    if(--IncomingCount == 0){
      XportStatus = XPORT_RESET;
    }
  }
  
}


void gas_count_debounce()
{
  static unsigned long last_interrupt_time_gas = 0;
  unsigned long interrupt_time_gas = millis();
  // If interrupts come faster than 150ms, assume it's a bounce and ignore
  if (interrupt_time_gas - last_interrupt_time_gas > 150)
  {
    confirm_pulse_gas_count = PULSE_COUNT_GAS_CONFIRM;
    confirm_pulse_gas = true;
  }
  last_interrupt_time_gas = interrupt_time_gas;
}

void wat_count_debounce()
{
  static unsigned long last_interrupt_time_wat = 0;
  unsigned long interrupt_time_wat = millis();
  // If interrupts come faster than 150ms, assume it's a bounce and ignore
  if (interrupt_time_wat - last_interrupt_time_wat > 150)
  {
    confirm_pulse_wat_count = PULSE_COUNT_WAT_CONFIRM;
    confirm_pulse_wat = true;
  }
  last_interrupt_time_wat = interrupt_time_wat;
}

void gsc_count_debounce()
{
  static unsigned long last_interrupt_time_gsc = 0;
  unsigned long interrupt_time_gsc = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time_gsc - last_interrupt_time_gsc > 200)
  {
    confirm_pulse_gsc_count = PULSE_COUNT_GSC_CONFIRM;
    confirm_pulse_gsc = true;
  }
  last_interrupt_time_gsc = interrupt_time_gsc;
}


void print_menu(){
  Serial.println();
  Serial.println();
  Serial.println("embedded Energy monitor");
  Serial.println("=======================");
  Serial.println("\t'p' -> pulse count value");
  Serial.println("\t's' -> second count value");
#ifdef ENABLE_ETHERNET_MODE
  Serial.println("\t't' -> get time via internet");
#endif
  Serial.println("\t'h' -> help");
  Serial.println();
  Serial.print(" your choice: ");
}

void process_char(char resp){
  switch(resp){
    case 'p':
      Serial.println();
      Serial.print("GSC pulse count value: ");
      Serial.println(GscPulseCount);
      Serial.println();
      Serial.print("GAS pulse count value: ");
      Serial.println(GasPulseCount);
      Serial.println();
      Serial.print("WAT pulse count value: ");
      Serial.println(WatPulseCount);
      break;
    case 's':
      Serial.println();
      Serial.print("second count value (GSC): ");
      Serial.println(SecondCount_GSC);
      Serial.print("second count value (GAS): ");
      Serial.println(SecondCount_GAS);
      Serial.print("second count value (WAT): ");
      Serial.println(SecondCount_WAT);
      break;
#ifdef ENABLE_ETHERNET_MODE
    case 't':
      Serial.println();
      Serial.print("time string: ");
      HttpMessage = HTTP_GET_TIME;
      HttpTransfer();
      break;
#endif
    case 'h':
      Serial.println();
      Serial.println("embedded monitor program (v1.1) written by Frederik Naessens");
      HttpMessage = HTTP_TEST_POST;
      HttpTransfer();
      break;
    default:
      Serial.print("Invalid choice");
  }
  print_menu();
}
